﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel.Syndication;

namespace RssReaderTemplate.Model.Mappers
{
    public class MapperProvider
    {
        private static IList<PartialMapper> _mappers = new List<PartialMapper>();

        public static void RegisterMapper<T>() where T : PartialMapper
        {
            RegisterMapper((PartialMapper)Activator.CreateInstance(typeof(T)));
        }

        

        public static void RegisterMapper(PartialMapper mapper)
        {
            if (mapper == null)
            {
                throw new ArgumentNullException("mapper");
            }
            if (_mappers.Any(m => m.GetType().Equals(mapper.GetType())))
            {
                throw new ArgumentException("Mapper already registered","mapper");
            }
            _mappers.Add(mapper);
        }

        public static ItemMapper CreateMapper(SyndicationItem rssItem)
        {
            if (CompositeMapper.Instance == null)
            {
                CompositeMapper.Instance = new CompositeMapper(GetTitleMapper(rssItem),
                    GetContentMapper(rssItem),
                    GetAuthorMapper(rssItem),
                    GetPublishDateMapper(rssItem));
            }
            return CompositeMapper.Instance;
        }

        public static PartialMapper GetTitleMapper(SyndicationItem item)
        {
            var mapingResults = from m in _mappers
                                select new { Map = m.MapTitle(item), Mapper = m };
            var res = mapingResults.Aggregate((best, current) => current.Map.Length > best.Map.Length ? current : best);
            return res.Mapper;
        }

        public static PartialMapper GetContentMapper(SyndicationItem item)
        {
            var mapingResults = from m in _mappers
                                select new { Map = m.MapContent(item), Mapper = m };
            var res = mapingResults.Aggregate((best, current) => current.Map.Length > best.Map.Length ? current : best);
            return res.Mapper;
        }

        public static PartialMapper GetAuthorMapper(SyndicationItem item)
        {
            var mapingResults = from m in _mappers
                                select new { Map = m.MapAuthor(item), Mapper = m };
            var res = mapingResults.Aggregate((best, current) => current.Map.Length > best.Map.Length ? current : best);
            return res.Mapper;
        }

        public static PartialMapper GetPublishDateMapper(SyndicationItem item)
        {
            var mapingResults = from m in _mappers
                                select new { Map = m.MapPublishDate(item), Mapper = m };
            var res = mapingResults.Aggregate((best, current) => current.Map > best.Map ? current : best);
            return res.Mapper;
        }
    }
}
